package similarity;

import java.sql.SQLException;

import odnoklassniki.OdnoklassnikiUserTrackSubmatrix;

import lastfm.LastfmUserTrackSubmatrix;
import musictrackrecommendation.Dataset;
import musictrackrecommendation.ExperimentParameters;
import randomwalk.Submatrix;
import simpledataset.SimpleMatrix;

public class LshSimilarityCalculations {
	
	private int dotProductsNumber = 10;//number of dot products in projection (k)
	private int projectionsNumber = 4;//number of projections (L)
	private double bucketWidth = 0.05;//size of each bucket (w)
	
	
	public void calculateUsersSimilarity() {
		try {			
			ExperimentParameters parameters = ExperimentParameters.getInstance();
			System.out.println(parameters.getTitle());
			
			Submatrix userTrack;
			
			int datasetType = parameters.getDatasetType();
			switch (datasetType) {
			case ExperimentParameters.LASTFM_SMALL_DATASET:
				userTrack = new LastfmUserTrackSubmatrix();
				break;
			case ExperimentParameters.SIMPLE_DATASET:
				userTrack = SimpleMatrix.getUserTrack();
				break;
			case ExperimentParameters.ODNOKLASSNIKI_DATASET:
				userTrack = new OdnoklassnikiUserTrackSubmatrix();
				break;
			default:
				userTrack = SimpleMatrix.getUserTrack();
			}
			
			normalizeByRows(userTrack);
			
			Dataset datasetProperties = 
				parameters.getDatasetProperties();
			
			int userVectorLength = datasetProperties.getTracksMaximalId()+1;
			int trackVectorLength = datasetProperties.getUsersMaximalId()+1;
			
			LshProjection [] projections = new LshProjection [projectionsNumber];
			//initialize projections
			for (int i = 0; i < projectionsNumber; i++) {
				projections [i] = new LshProjection(dotProductsNumber,bucketWidth, userVectorLength);
			}
			//project multidimensional data
			for (LshProjection projection : projections) {
				projection.calculateHashes(userTrack, trackVectorLength);
			}

		} catch (ClassNotFoundException e) {
			System.out.println("Cannot register JDBC driver");
			e.getMessage();
		} catch (SQLException e) {
			System.out.println("Cannot retrieve data from database");
			e.getMessage();
		}
	}

	public void normalizeByRows(Submatrix userTrack) {
		ExperimentParameters parameters = ExperimentParameters.getInstance();
		Dataset datasetProperties = parameters.getDatasetProperties();

		int usersCount = datasetProperties.getUsersMaximalId();
		int tracksCount = datasetProperties.getTracksMaximalId();

		double[] usersRowNorms = new double[usersCount + 1];
		double[] tracksRowNorms = new double[tracksCount + 1];

		for (int i = 0; i < userTrack.getRowIds().length; i++) {
			// count UserTrack elements
			tracksRowNorms[userTrack.getColumnIds()[i]] += userTrack
					.getTransponedSubmatrixValues()[i];
			// count TrackUser elements
			usersRowNorms[userTrack.getRowIds()[i]] += userTrack
					.getValues()[i];
		}

		// normalize UserTrack elements
		for (int i = 0; i < userTrack.getValues().length; i++) {
			userTrack.getValues()[i] /= usersRowNorms[userTrack
					.getRowIds()[i]];
			userTrack.getTransponedSubmatrixValues()[i] /= tracksRowNorms[userTrack
					.getColumnIds()[i]];
		}
	}
	
}
